perm filename DVIALF.SAI[ALF,DEK] blob sn#500175 filedate 1980-03-22 generic text, type T, neo UTF8
begin "dvialf" comment convert DVI files to files that go to the Alphatype
			THIS IS A PRELIMINARY, NON-OPTIMAL VERSION by drf ;
define # = "comment ";
define crlf = "'15&'12";
require "{}{}" delimiters;
define thru = { step 1 until };
define L1={ ((((4)*16+0)*16+2)*16+0) };
define R1={ ((((7)*16+3)*16+0)*16+0) };
define L2={ ((((8)*16+5)*16+0)*16+14) };
define R2={ ((((11)*16+12)*16+1)*16+8) };
define compensation={ 1421 };
comment define LCOG={ (2048) };
comment define RCOG={ (2048+900) };
define A={ 1365 }; define B={2047};
define PSH={20}; # stack size;

define	NOP={128}, BOP={129}, EOP={130}, PST={131}, 
	DVIPUSH={132}, DVIPOP={133},
	VERTRULE={134}, HORZRULE={135}, HORZCHAR={136}, DVIFONT={137},
	W4={138}, W3={139}, W2={140}, W0={141},
	X4={142}, X3={143}, X2={144}, X0={145},
	Y4={146}, Y3={147}, Y2={148}, Y0={149},
	Z4={150}, Z3={151}, Z2={152}, Z0={153},
	FONTNUM={154}; # to 217;

external integer !skip!;
integer dbug,tdbug,ebug;

integer dvi,ant,alf,dviw,dvibytecnt;
string filename,s;

integer w,h,i,j,k,v;
integer array accs[0:'17];

integer c,addr,dx;
integer lmarg,tmarg,bmarg,pagelimit,ask;
integer mark,nv,id;
integer lastw,lastx,lasty,lastz;
integer array pshwamt[0:PSH], pshxamt[0:PSH], pshyamt[0:PSH], pshzamt[0:PSH],
	pshx[0:PSH], pshy[0:PSH]; integer stkptr;
integer x,y;
integer pagecycle,cyclecnt; integer array xcycle[0:9], ycycle[0:9];
integer lcog,rcog;

preload!with [65] -1;
integer array fontptr[0:64];
string array fontname[0:64];
integer oword, wordcnt;
integer postambleptr;
integer pagecnt,pageno;
integer fontno,maxpageheight,maxpagewidth,lastpageptr;
integer memptr;
integer array ano[0:64,0:127];
integer array yx[0:8000]; integer array fcp[0:8000]; integer yxfcptr;
integer array mem[0:60000]; # holds font files;

procedure error(string err); begin integer i;
	print(crlf,crlf,err,crlf);
	start!code
		movei 0,'123456;
		movei 1,0;
		haltf;
		end;
	end;

procedure push; begin
	if stkptr>PSH then error("STACK OVERFLOW-YOU LOSE!");
	pshx[stkptr]←x; pshy[stkptr]←y;
	pshwamt[stkptr]←lastw;
	pshxamt[stkptr]←lastx;
	pshyamt[stkptr]←lasty;
	pshzamt[stkptr]←lastz;
	stkptr←stkptr+1;
	end;

procedure pop; begin
	stkptr←stkptr-1;
	if stkptr<0 then error("STACK UNDERFLOW BUG!");
	x←pshx[stkptr]; y←pshy[stkptr];
	lastw←pshwamt[stkptr];
	lastx←pshxamt[stkptr];
	lasty←pshyamt[stkptr];
	lastz←pshzamt[stkptr];
	end;

integer procedure getb; begin integer r;
	r←(dviw lsh -24) land '377;
	dviw←dviw lsh 8;
	dvibytecnt←dvibytecnt+1;
	if (dvibytecnt land 3)=0 then dviw←wordin(dvi); 
	return(r);
	end;

procedure gotobyte(integer n); begin integer w,r;
	w←n div 4; r←n-(w*4);
	swdptr(dvi,w);
	dviw←wordin(dvi) lsh (8*r);;
	dvibytecnt←n;
	end;

integer procedure twobytes; begin integer n;
	n←(getb lsh 8) lor getb ;
	return((n lsh 20) ash -20);
	end;

integer procedure threebytes; begin integer n;
	n←(((getb lsh 8) lor getb) lsh 8) lor getb ;
	return((n lsh 12) ash -12);
	end;

integer procedure fourbytes; begin integer n;
	n←(((((getb lsh 8) lor getb) lsh 8) lor getb) lsh 8) lor getb;
	return((n lsh 4) ash -4);
	end;

procedure o(integer n); begin
	oword←(oword lsh 9) lor '400 lor (n land '377);
	if (oword<0) then begin
		wordout(alf,oword rot wordcnt);
		wordcnt←(wordcnt+1) mod 17;
		oword←0;
		end;
if dbug then print(" out '",cvos(n land '377),crlf);
	end;

define oo(n)={ begin o(n); o(n lsh -8); end };

integer procedure du(integer n); return( (n/(2↑16)) * (32000/9) / 72.27);
integer procedure fu(integer n); return( (n/(2↑16)) * (8000/5)  / 72.27);

procedure setchar(integer c,flag); begin 
	integer cptr,sptr,parts,part,width;
	cptr←fontptr[fontno]+c;
	parts←mem[cptr] lsh -18;
	sptr←fontptr[fontno] + (mem[cptr] land '777777);
	width←mem[3+sptr] lsh -2;
	for part←0 step 1 until parts-1 do begin
		integer netx,nety,xoffset,yoffset,bytetimes;
		bytetimes←mem[sptr+2] lsh 18;
		if bytetimes=0 then continue;
		xoffset←mem[sptr] ash -18;
		yoffset←(mem[sptr] lsh 18) ash -18;
		yxfcptr←yxfcptr+1;
		netx←du(x)-xoffset+xcycle[pagecycle];
		nety←fu(y)-yoffset+ycycle[pagecycle];
IF EBUG then PRINT("char "&c,if part then "."&cvos(part) else ""," at ",
	netx," du = ",du(x),"-",xoffset,"+",xcycle[pagecycle],", ",
	nety," fu = ",fu(y),"-",yoffset,"+",ycycle[pagecycle],crlf);
IF XOFFSET NEQ 0 OR NETX<0 OR NETX>55487 OR NETY<0 OR NETY>29190 THEN 
	PRINT("LUMPH ",INTTY);
		yx[yxfcptr]←(nety lsh 18) lor netx;
		fcp[yxfcptr]←(fontno lsh 14) lor
				((c LAND '177) lsh 7) lor part;
		sptr←sptr+4;
		end;
	if flag then x←x+width;
	end;

procedure touchfont(integer fontno); begin string s;
	if fontptr[fontno]>-1 then return;
	s←fontname[fontno]; 
PRINT(crlf,"loading ",s," at ",memptr);
	ant←openfile(s&".ANT","ROE");
	if !skip! then begin
		while (lop(s) neq ">") do begin end;
		ant←openfile(s&".ANT","ROE");
		end;
	if !skip! then error(s&" -- FONT MISSING!");
	fontptr[fontno]←memptr;
	arryin(ant,mem[memptr],99999);
	memptr←memptr+ (!skip! land '777777); 
PRINT(" used ",!skip! land '777777,crlf);
	cfile(ant);
	end;

procedure chngmult(integer newa,newb); begin
if ebug then print("Changing multipliers to A=",newa,", B=",newb,crlf);
	o(1); oo(newa); oo(newb);
	end;

procedure dispm(string s); begin integer i,l;
if ebug then print("Display: ",s,crlf);
	l←length(s);
	o(0); o(0); o(l); for i←1 thru l do o(lop(s)); end;

procedure bpage(integer g,y,p); begin
if ebug then print("Begin page g=",g," y=",y," p=",p,crlf);
	o(0); o(1); oo(g); oo(y); oo(p); end;

procedure adjust(integer d); begin
if ebug then print("Adjust cogs ",d,crlf);
	o(0); o(0); o(0); oo(d); end;

procedure set(integer c,x,g,h); begin 
if ebug then print("Set ",c," at ",x," g=",g," h=",h,crlf);
	o(c); oo(x); o(g); o(h); end;

procedure eoln(integer g); begin
if ebug then print("Eoln at ",g,crlf);
	o(0); o(2); oo(g); end;

procedure feed(integer y); begin
if ebug then print("Feed ",y,crlf);
	o(2); o(2); oo(y); end;

procedure eofilm; begin
print("End film",crlf);
dispm("EOFILM...");
	o(2); o(1); end;

procedure chngbrit(integer newbrit); begin 
if ebug then print("Change brightness to ",newbrit,crlf);
	o(2); o(0); oo(newbrit); end;

integer procedure loadalf(integer fromhere); begin
	integer m,actr,f,c,sgptr,parts,i,j,k,bptr,w,x,bytes;
	arrclr(ano);
	m←L1;
	actr←3;
	bpage(LCOG,(yx[fromhere] lsh -18),pageno);
	for i←fromhere thru yxfcptr do begin "loadupmem"
		f← (fcp[i] lsh -14) land '77;
		c← (fcp[i] lsh -7) land '177;
		if ano[f,c]>0 then continue;
		ano[f,c]←actr;
		sgptr←(mem[fontptr[f]+c] land '777777) + fontptr[f];
		parts←mem[fontptr[f]+c] lsh -18;
		for j← 1 thru parts do begin
			bptr←(mem[sgptr+2+4*(j-1)] land '777777)+fontptr[f];
			bytes←mem[bptr];
			if (m<R1) and (m+bytes+4 geq R1) then m←L2;
			if (m+bytes+4 geq R2) then done "loadupmem";
comment dispm("D"&CVS(actr));
if ebug then print("loading ",f," '",cvos(c)," ",j," as ",actr,
	" at ",m," ('",cvos(m),") for ",bytes,crlf);
			o(0); o(actr); oo(m); oo(bytes);
			actr←actr+1;
			m←m+bytes+4;
			x←mem[fontptr[f]+128];
			tdbug←dbug; dbug←0;
			for k←0 thru bytes-1 do begin
				if (k land 3)=0 then begin
					bptr←bptr+1;
					x←x*367965721+256854611;
					w←mem[bptr] xor (x lsh -4);
					end;
				o(w lsh -24);
				w←w lsh 8;
				end;
			dbug←tdbug;
			end;
		end; 
DISPM("E");
	return(i-1);
	end;


procedure outalf(integer fromhere, tothere); begin 
	integer i,rl,y,newy,alfy,cnt,lastcnt,newg,newh,ritebit,leftbit,
			g,h,oldh,t,x,sgptr,f,c,p,bytetimes,newbytetimes,
			dropit,firstdropped,dg,dh,d;
	y←alfy←yx[fromhere] lsh -18;
	rl←1;
	i←fromhere;
	cnt←0;
	while i leq tothere do begin
		rl←1-rl;
		adjust(rl*compensation/32);
		g←h←oldh←LCOG+rl*(compensation/32);
		lastcnt←cnt;
		cnt←0;
		bytetimes←0;
		firstdropped←-1;
comment uncomment following line for one-way typesetting, else 2-way;
comment IF NOT RL THEN; 
		while true do begin
			while fcp[i]<0 and i leq tothere do i←i+1;
			if i>tothere then done;
			if (yx[i] lsh -18)>y then done;
			if lastcnt+cnt>197 then done;
			f← (fcp[i] lsh -14) land '77;
			c← (fcp[i] lsh -7) land '177;
			p← fcp[i] land '177;
			sgptr←(mem[fontptr[f]+c] land '777777)+fontptr[f]+4*p;
			newbytetimes← mem[sgptr+2] lsh -18;
			x←rl*compensation+ (yx[i] land '777777);
			leftbit←mem[sgptr+1] lsh -18;
			ritebit←mem[sgptr+1] land '777777;
			newg←((((leftbit*A) lsh -11)-((360*A) lsh -11)+x)
					lsh -5) + 2048;
			newh←((((ritebit*A) lsh -11)-((360*A) lsh -11)+x)
					lsh -5) + 2048;
			dropit←0;
			if (g geq newg) then dropit←1;
			if (h geq newh) then dropit←dropit+2;
			if (newg leq oldh) then dropit←dropit+4;
			if ((newg leq h) and (newbytetimes+bytetimes>1021))
				then dropit←dropit+8;
			if dropit then begin 
					if firstdropped=-1 then firstdropped←i;
if ebug then print(" dropped f",f," "&c&"'",cvos(c)," p",p," cause ",dropit, 
  " g",g," newg",newg," h",h," newh",newh," x",x); 
					i←i+1;
					continue;
					end;
			dg←newg-g; dh←newh-h;
if ebug then print("put f",f," "&c&"'",cvos(c)," p",p," x",x," lbit",leftbit,
 " rbit",ritebit," ng",newg," dg",dg," nh",newh," dh",dh," bt",bytetimes,crlf);
IF DG<0 OR DH<0 THEN PRINT("WHOOPS!!",INTTY);
			if dg>255 or dh>255 then begin
				d←dg min dh;
				adjust(d);
				g←g+d; h←h+d;
				cnt←cnt+1;
				end;
			set(ano[f,c]+p,x,newg-g,newh-h);
			oldh←h; g←newg; h←newh; bytetimes←newbytetimes;
			cnt←cnt+1;
			fcp[i]←-1;
			i←i+1;
			end;

		if rcog<h then print(intty,"OH NO",intty);
comment		adjust(((RCOG-h)*32+compensation)/32);
		adjust(RCOG-h);

		if firstdropped>0 then i←firstdropped
		else while fcp[i]<0 and i leq tothere do i←i+1;
		if i<=tothere then begin
			newy←yx[i] lsh -18;
			if newy>alfy+1 then begin
				feed(newy-alfy);
				alfy←newy;
				end;
			y←newy;
			end;

		if rl then eoln(LCOG)
		else eoln(RCOG+compensation/32); comment hack;

		end;
	end;


procedure sort; begin "sort" integer i,delta;
	delta←1; while 9*delta+3<yxfcptr do delta←3*delta+1;
	while delta>0 do begin
		for i←delta step 1 until yxfcptr do
			if yx[i-delta]>yx[i] then begin integer j,k,t1,t2;
				j←i-delta; 
				t1←yx[i]; t2←fcp[i];
				k←i;
				do begin
					yx[k]←yx[j]; fcp[k]←fcp[j];
					k←j; j←j-delta;
					end until j<0 or yx[j] leq t1;
				yx[k]←t1; fcp[k]←t2;
				end;
		delta←delta div 3;
		end;
	end "sort";

comment main program ;
dbug←0; ebug←0;
oword←wordcnt←0;
arrclr(fontptr,-1);

print(".DVI file: ");
filename←intty;
s←filename&".ALF";
filename←filename&".DVI";
print("Input from ",filename,crlf);
dvi←openfile(filename,"ROE");
if !skip! then error("Couldn't open "&filename);
alf←openfile(s,"WE");
if !skip! then error("Couldn't open "&s);


swdptr(dvi,-1);
postambleptr←(rwdptr(dvi))*4-3;
gotobyte(postambleptr←postambleptr-1);
if getb neq 223 then error("No Postamble -- bad DVI file.");
while true do begin integer t;
	gotobyte(postambleptr←postambleptr-1);
	if (t←getb) = 0 then done;
	if t neq 223 then error("Bad DVI file format");
	end;
gotobyte(postambleptr←postambleptr-4);
postambleptr←fourbytes;
# PRINT("POSTAMBLE AT BYTE ",POSTAMBLEPTR,".  ");
gotobyte(postambleptr);

if getb neq PST then error("Bad DVI file format");
lastpageptr←fourbytes;
maxpageheight←fu(fourbytes);
maxpagewidth←du(fourbytes);

while true do begin "get font names"
	if (id←fourbytes) = -1 then done;
	fontno←fourbytes;
	s←""; mark←getb; while (nv←getb) neq mark do s←s&nv;
	fontname[fontno]←s;
	end "get font names";

cyclecnt←6; pagecycle←0;

xcycle[0]←1024;		xcycle[1]←19168-320;	xcycle[2]←37312-640;
ycycle[0]←ycycle[1]←ycycle[2]←1000-1000;

xcycle[3]←1024;		xcycle[4]←19168-320;	xcycle[5]←37312-640;
ycycle[3]←ycycle[4]←ycycle[5]←14752-2000;

pagelimit←6;
ASK←1; 
if ask then begin
	print("Starting at page (default=first) ");
	s←intty;
	if s then begin
		i←cvd(s);
		while true do begin
			gotobyte(lastpageptr);
			if getb neq BOP then error("Bad beginning of page");
			if fourbytes=i then done;
			if (lastpageptr←fourbytes)=-1 then 
				error("No such page");
			end;
		gotobyte(lastpageptr);
		end
	else gotobyte(0);
	print("Number of pages (default=6) ");
	s←intty;
	if s then pagelimit←cvd(s);
	end
else gotobyte(0);

chngbrit(2700);
chngmult(A,B);

while true do begin "do a command";
	while (v←getb) geq FONTNUM do touchfont(fontno←v-FONTNUM);
	case v of begin "case stmt"
	[NOP] begin # PRINT("N"); end;
	[BOP] begin "BOP" yxfcptr←-1; 
		x←y←24*(1 lsh 16); # left and top margin of 24 points;
		print(" [",pageno←FOURBYTES); FOURBYTES; 
		pagecnt←pagecnt+1;
		end "BOP";
	[EOP] begin "EOP" integer fromhere, tothere;
		sort; print("]");
		lcog←2048+(xcycle[pagecycle] div 32);
		rcog←lcog+750;
if ebug then PRINT("LCOG ",lcog," RCOG ",rcog,crlf);
		fromhere←0; tothere←-1;
		while (tothere<yxfcptr) do begin
			tothere←loadalf(fromhere);
comment PRINT(" FROM ",FROMHERE," TO ",TOTHERE,CRLF);
			outalf(fromhere,tothere);
			fromhere←tothere+1;
			end;
		if pagecnt>=pagelimit then done;
		pagecycle←pagecycle+1;
		if pagecycle=cyclecnt then begin eofilm; pagecycle←0; end;
		end "EOP";
	[HORZRULE]
	[VERTRULE] begin "RULE" integer height,width,yoffset,xoffset,h,w;
		height←fourbytes; width←fourbytes; h←fu(height); w←du(width);
		comment yxfcptr←yxfcptr+1;
		comment yx[yxfcptr]← (fu(y) lsh 18) lor du(x);
		comment fcp[yxfcptr]←(3 lsh 34);
		if v=VERTRULE then x←x+width; end "RULE";
	[HORZCHAR] begin c←getb; setchar(c,0); end;
	[DVIFONT] touchfont(fontno←fourbytes);
	[DVIPUSH] push;
	[DVIPOP] pop;
	[W0] x←x+lastw;
	[W2] begin lastw←twobytes; x←x+lastw; end;
	[W3] begin lastw←threebytes; x←x+lastw; end;
	[W4] begin lastw←fourbytes; x←x+lastw; end;
	[X0] x←x+lastx;
	[X2] begin lastx←twobytes; x←x+lastx; end;
	[X3] begin lastx←threebytes; x←x+lastx; end;
	[X4] begin lastx←fourbytes; x←x+lastx; end;
	[Y0] y←y+lasty;
	[Y2] begin lasty←twobytes; y←y+lasty; end;
	[Y3] begin lasty←threebytes; y←y+lasty; end;
	[Y4] begin lasty←fourbytes; y←y+lasty; end;
	[Z0] y←y+lastz;
	[Z2] begin lastz←twobytes; y←y+lastz; end;
	[Z3] begin lastz←threebytes; y←y+lastz; end;
	[Z4] begin lastz←fourbytes; y←y+lastz; end;
	[PST] done;
	else setchar(v,1)
	end "case stmt";

	end "do a command";
eofilm;
print(crlf);
wordout(alf,oword rot wordcnt); # force out remaining buffer;
cfile(dvi); cfile(alf);
start!code
	comment haltf;
	end;
end "dvialf";